zygote进程定义
Init进程是Android系统中用户空间的第一个进程, 它最重要的工作就是创建zygote进程。而在Android系统中,所有应用程序的进程以及系统服务进程SystemServer都是由Zygote进程孕育出来的。所有Zygote的地位非同小可,本文就分析它的启动过程。
Android系统启动后运行的第一个进程是init进程,它的目录在system/core/init/init.cpp 在这里会进行启动属性服务以及解析init.rc文件,init.rc文件是android系统的配置文件,它如下格式所示:
1 | system/core/rootdir/init.rc |
每一个service命令都会促使init进程调用fork函数来创建一个新的进程,这里service用于通知init进程创建名zygote的进程,这个zygote进程执行程序的路径为/system/bin/app_process,后面的则是要传给app_process的参数。class main指的是zygote的class name为main。
zygote要执行的程序是system/bin/app_process这样会进入main函数。在main中会执行AppRuntime的start来进一步启动zygote。
frameworks/base/cmds/app_process/app_main.cpp
1 | int main(int argc, char* const argv[]) |
这里的runtime是AppRuntime的实例,AppRuntime是继承自AndroidRuntime,这里的start方法就是在AndroidRuntime里定义的。
//启动android运行时 这包括了启动虚拟机和调用callName所定义的静态main方法 这里时指com.android.internal.os.ZygoteInit
frameworks/base/core/jni/AndroidRuntime.cpp
1 | void AndroidRuntime::start(const char* className, const char* options) |
Zygote进程在启动时会创建JavaVM,因此通过fock而创建的应用程序进程和SystemServer进程可以在内部获取一个JavaVM的实例拷贝.在启动zygote时传递进来的类为com.android.internal.os.ZygoteInit,这里通过反射的方式来调用其main方法进一步完成启动初始化的过程。
1 | //在AndroidRuntime的start方法通过反射调用的 |
在zygote的初始化中,做了以下几件事件:
- 通过registerServerSocket创建zygote的socket服务,它是一个LocalSocketServer用来等待AMS请求zygote创建应用进程的请求。
- 监听socket服务,等待AMS创建应用程序的请求
- 创建SystemServer进程
值得注意的是,无论是创建systemServer进程还是创建应用进程,最终都会通过捕获MethodAndArgsCaller异常来执行参数指定的class的main方法,后面我们分析SystemServer启动及应用进程的启动时就会看到。
这里我们接着看看注册socket服务的代码,它仅仅是创建了LocalServerSocket的本地socket对象
1 | private static void registerZygoteSocket() { |
SystemServer进程的创建流程
这里我们重点关注SystemServer的创建流程,继续关注startSystemServer
1 | private static boolean startSystemServer() |
在startSystemServer中仅仅fork出进程后随后进一步在handleSystemServerProcess中进一步对SystemServer进行初始化
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
1 | private static void handleSystemServerProcess(//进一步处理SystemServer进程的相关工作 |
这里进一步调用zygoteInit进行初始化工作
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
1 | public static final void zygoteInit(int targetSdkVersion, String[] argv) |
首先我们来看第一个方法nativeZygoteInit的调用,这个方法时在AndroidRuntime中定义的,具体是
/frameworks/base/core/jni/AndroidRuntime.cpp
1 | static void |
这里的onZygoteInit是调用其子类AppRuntime的方法,zygote的启动就是通过这个类调用start方法来执行的。
frameworks/base/cmds/app_process/app_main.cpp
1 | virtual void onZygoteInit() |
ProcessState对于binder机制非常重要,这里主要是初始化SystemServer进程的的binder环境,这样在其进程中就可以通过binder同其他进程进行通信了。
下面我们来看看第二个方法applicationInit,这个方法第二个参数包含了调用了类的信息及相关方法的参数,这里就是com.android.server.SystemServer和main方法
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
1 | private static void applicationInit(int targetSdkVersion, String[] argv) |
这个方法内部会调用invokeStaticMain方法。
1 | //这个方法最终会抛出异常MethodAndArgsCaller触发其run方法的调用,具体见ZygoteInit的main方法 |
MethodAndArgsCaller的定义如下,这里我们重点看看run方法,run方法的实现很简单只是对main方法进行调用。即调用SystemServer的main方法完成SystemServer进程的创建和启动。
1 | public static class MethodAndArgsCaller extends Exception |
应用进程的创建启动过程
接下来我们分析应用进程创建和启动的过程,这个过程中需要AMS的介入,不过这里我们重点关注应用进程的创建和启动过程,而不需要关注整个流程的太多细节。熟悉AMS的应该知道,当我们点击Launcher启动应用程序后 最终会通过AMS的startProcessLocked方法来为我们的应用程序创建进程,而其内部会进一步调用startProcessLocked来完成,所以我们重点看那startProcessLocked方法。
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
1 | private final void startProcessLocked(ProcessRecord app, |
这个方法会通过Process的start方法类完成进程的创建,这里我们传递ActivityThread的类名,再我们创建完应用进程后需要就是调用其内部的main方法完成启动过程。下面我们继续去看下进程是如何创建的。
frameworks/base/core/java/android/os/Process.java
1 | public static final ProcessStartResult start(final String processClass, |
Process的start方法很简单,调用startViaZygote,从其名称来看就是通过zygote来创建我们应用进程了。这里的processClass就是我们的ActivityThread类,niceName是进程名称。startViaZygote通过将这一些参数打包到一个ArrayList变量中然后调用zygoteSendArgsAndGetResult,并将打包的参数传递给它。这个方法负责将这些参数通过socket传递给zygote.
1 | private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args) |
这个方法首先通过openZygoteSocketIfNeeded方法来打开同zygote通信的socket,并用该socket创建一个BufferedWriter对象sZygoteWrite,随后通过sZygoteWrite将参数发送给zygote,同时创建一个ProcessStartResult对象,用来保存创建的进程信息。
对于zygote端我们知道,当zygote启动后会先注册一个LocalSocketServer服务,然后通过runSelectLoop等待来自AMS创建进程的请求。这里我们就需要看看runSelectLoop方法。
1 | private static void runSelectLoop() throws MethodAndArgsCaller { |
runSelectLoop方法主要负责处理客户端的连接请求和客户端的消息处理,当index==0是说明有新的客户端连接,index>0则说明有消息到来,index指定了客户端的连接索引。同时会调用runOnce对消息机型处理。
1 | //zygote收到客户端AMS的信息进行处理 |
在这个方法中首先通过readArgumentList方法读取客户端发送的消息,得到参数列表,随后根据参数创建应用进程,随后进一步调用handleChildProc进一步完成子进程的创建。在这个方法中最终会抛出MethodAndArgsCaller异常来触发run方法的调用,就如SystemServer进程那样。
1 | private void handleChildProc(Arguments parsedArgs, |
这个方法会调用invokeStaticMain,这个方法我们在SystemServer启动时候分析过,这里就不再分析了。最终会调用ActivityThread的main方法完成应用进程的启动。